home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / ALIAS.ZIP / ALIASWC.C < prev    next >
C/C++ Source or Header  |  1996-04-09  |  31KB  |  1,116 lines

  1. /*
  2. Scaling, Rotation, Antialiasing prototyper. revision 3.
  3.  
  4. This program was written by Lewis A. Sellers (Minimalist)
  5. of The Minimalist Group, and the MOSOCI Grail Project in
  6. 1995-1996 Anno Dominus.
  7.  
  8. While it is the result of several days of work on my part, fiddled
  9. with here and there over a few months as time permits, you can use
  10. it and the code involved if you wish as intas you include the standard
  11. greetings to me somewhere in your program, say in the credits.
  12.  
  13. You must supply a BMP filename as an argument such as:
  14. C:> ALIAS DEATH.BMP
  15. The BMP can be any size, grayscale or color, so long as it is 8-bit color.
  16.  
  17. This originally was written with borland turbo c++ 3.0 simply because it
  18. was easy to do so. To get a speed increase I tried using Borland C++ 4.52
  19. which I bought a while back. Most of the new Borland stuff is much more
  20. complicated than needs be so I hadn't used it much, but I did get about an
  21. extra two FPS from the recompile.
  22.  
  23. I also wrote a pascal version while teaching myself pascal on the IBMs.
  24.  
  25. This is the 32-bit WATCOM version. While there is an older Borland 16-bit
  26. version (aliasc.c) and a Turbo Pascal version (aliaspas.pas) this is the
  27. only one that is currently being revised and improved.
  28.  
  29. This program is designed for at least the 486 processors. Preferably pentiums.
  30.  
  31. Probably it'll end up as some kind of tutorial one day.
  32.  
  33. PLEASE READ ALIAS.TXT
  34.  
  35. --MIN (rhymes with NIN)
  36.  
  37.   "the me that you know is now made up of wires
  38.    and even when i'm right with you i'm so far away" --NIN
  39. */
  40.  
  41. #include <stdlib.h>
  42. #include <conio.h>
  43. #include <malloc.h>
  44. #include <stdio.h>
  45. #include <time.h>
  46. #include <dos.h>
  47. #include <math.h>
  48. #include <mem.h>
  49.  
  50. //general defines
  51. #define FALSE (1==0)
  52. #define TRUE  (1==1)
  53.  
  54. #define FAILURE 0
  55. #define SUCCESS 1
  56.  
  57. typedef unsigned char byte;
  58. typedef unsigned short int word;
  59. typedef unsigned int dword;
  60.  
  61. //prototypes
  62. void change_timer(void);
  63. void restore_timer(void);
  64.  
  65. void mode_graphic(void);
  66. void mode_text(void);
  67.  
  68. int LoadTestImage(char *name);
  69. void setup_fps(void);
  70. void print_fps(int fps);
  71.  
  72. void bilinear(void);
  73. void trilinear(void);
  74. void hyperlinear(void);
  75. void color_bilinear(void);
  76. void color_trilinear(void);
  77. void color_hyperlinear(void);
  78.  
  79. void copycomposite(void);
  80. void clearcomposite(void);
  81. //int lines(void);
  82.  
  83.  
  84. //TIMER
  85. #define PIT_FREQUENCY  0x1234DDL
  86. #define frequency      100
  87. #define counter        PIT_FREQUENCY/frequency
  88.  
  89. volatile int BIOS_ticks=0;
  90. volatile int second_ticks=0;
  91. volatile int second_flag=FALSE;
  92.  
  93. void (__interrupt __far *prev_int_1c)();
  94.  
  95. void __interrupt __far timerhandler()
  96. {
  97.     BIOS_ticks+=counter;
  98.     second_ticks++;
  99.     if(BIOS_ticks>=0x10000) {
  100.         BIOS_ticks=0;
  101.         _chain_intr(prev_int_1c);
  102.     }
  103.     if(second_ticks>=100) {
  104.         second_flag=TRUE;
  105.         second_ticks=0;
  106.     }
  107.     outp(0x20,0x20);
  108. }
  109.  
  110.  
  111. void change_timer()
  112. {
  113.     //swap out the BIOS handler for our own....
  114.     prev_int_1c=_dos_getvect(0x1c);
  115.     _dos_setvect(0x1c,timerhandler);
  116.     //change the clock frequency to 100 per second
  117.     outp(0x43,0x34);
  118.     outp(0x40,(byte)(counter%256));
  119.     outp(0x40,(byte)(counter/256));
  120. }
  121.  
  122.  
  123. void restore_timer()
  124. {
  125.     //restore 18.2 frequency of PIT 0
  126.     outp(0x43,0x34);
  127.     outp(0x40,0);
  128.     outp(0x40,0);
  129.     //restore the BIOS tick handler
  130.     _dos_setvect(0x1c,timerhandler);
  131. }
  132.  
  133.  
  134. //constant
  135. #define WIDTH           320
  136. #define HEIGHT          200
  137. #define WIDTH_CENTER    160
  138. #define HEIGHT_CENTER   100
  139. #define WIDTH_OFFSET    60
  140. #define HEIGHT_OFFSET   0
  141.  
  142. #define W_WIDTH         200
  143. #define W_HEIGHT        200
  144. #define W_WIDTH_CENTER  100
  145. #define W_HEIGHT_CENTER 100
  146.  
  147. #define W_LEFT   60
  148. #define W_RIGHT  260
  149. #define W_TOP    0
  150. #define W_BOTTOM 200
  151.  
  152. #define T_WIDTH         256
  153. #define T_HEIGHT        256
  154. #define T_WIDTH_CENTER  128
  155. #define T_HEIGHT_CENTER 128
  156.  
  157. #define T_LEFT   0
  158. #define T_RIGHT  256
  159. #define T_TOP    0
  160. #define T_BOTTOM 256
  161.  
  162. char *G_BASE=(char *)(0xa0000); //graphics memory
  163.  
  164.  
  165. //GRAPHICS
  166. #define PI 3.14159
  167.  
  168. char *texture;
  169. int *y320;
  170. char *composite;
  171. struct rgb_struct {
  172.     byte red;
  173.     byte green;
  174.     byte blue;
  175. } *palette;
  176. byte *palette_matrix;
  177.  
  178. typedef struct {
  179.     //fileformat
  180.     word type; //42 4d BM
  181.     dword filesize; //36 fe
  182.     word unused1;
  183.     word unused2;
  184.     dword offsetbits; //0c
  185.     //info
  186.     dword infosize;
  187.     word width; //c8 00
  188.     word w1;
  189.     word height;
  190.     word h1;
  191.     word planes; //1
  192.     byte bitcount; //8
  193.     dword compression; //0
  194.     dword imagesize; //00 00 fa 00
  195.     dword xpels;
  196.     dword ypels;
  197.     dword colorsused;
  198.     dword colorsimportant;
  199.     byte u1;
  200. } bmp_struct;
  201.  
  202.  
  203. //
  204. void mode_graphic(void);
  205. #pragma aux mode_graphic = \
  206.     "mov ax,13h" \
  207.     "int 10h" \
  208.     "mov dx,03c2h" \
  209.     "mov al,0e3h" \
  210.     "out dx,al" /* put it in square mode */ \
  211.     "mov dx,0x3c6" \
  212.     "mov ax,0xff" \
  213.     "out dx,al" \
  214.     "mov dx,0x3c8" \
  215.     "mov al,0" \
  216.     "out dx,al" \
  217.     "mov dx,0x3c9" \
  218.     "mov esi, [palette]" \
  219.     "mov ecx,768" \
  220.     "mgloop:" \
  221.     "mov al,[esi]" \
  222.     "out dx,al" \
  223.     "inc esi" \
  224.     "sub ecx,1" \
  225.     "jnz mgloop" \
  226.     modify [ax dx esi];
  227.  
  228.  
  229. void mode_text(void);
  230. #pragma aux mode_text = \
  231.     "mov ax,3" \
  232.     "int 10h" \
  233.     modify [ax];
  234.  
  235.  
  236. //load in a grayscale 320x200 BMP
  237. int LoadTestImage(char *name)
  238. {
  239.     FILE *bmp;
  240.     int x,y;
  241.     int n;
  242.     byte *thrash;
  243.     bmp_struct *bf;
  244.     char *source,*destination;
  245.     int w,h,w_src,h_src,w_dst,h_dst;
  246.     int BWIDTH;
  247.     struct rgba_struct {
  248.         byte blue;
  249.         byte green;
  250.         byte red;
  251.         byte alpha;
  252.     } *temp_palette;
  253.  
  254.     //
  255.     bmp=fopen(name,"rb");
  256.     if(bmp==NULL) return FAILURE;
  257.  
  258.     //
  259.     bf=(bmp_struct *)malloc(sizeof(bmp_struct));
  260.     if(bf==NULL) {
  261.         mode_text();
  262. //      printf("Not enough memory (%lu) for BMP header.\n",farcoreleft());
  263.         exit(FAILURE);
  264.     }
  265.     fread(bf,sizeof(bmp_struct),1,bmp);
  266.  
  267.     if(bf->bitcount!=8) {
  268.         mode_text();
  269.         printf("The bitmap must be 8-bit (256 color).\n");
  270.         exit(FAILURE);
  271.     }
  272.  
  273.     //PALETTE
  274.     //from b-g-r-unused dword format to proper RGB 3byte.
  275.     temp_palette=(void *)malloc(4*256);
  276.     if(temp_palette==NULL) {
  277.         mode_text();
  278. //      printf("Not enough memory (%lu) for temp palette.\n",farcoreleft());
  279.         exit(FAILURE);
  280.     }
  281.     fread(temp_palette,4*256,1,bmp);
  282.     for(n=0;n<256;n++)
  283.     {
  284.         palette[n].red=(temp_palette[n].red>>2);
  285.         palette[n].green=(temp_palette[n].green>>2);
  286.         palette[n].blue=(temp_palette[n].blue>>2);
  287.     }
  288.     free(temp_palette);
  289.  
  290.     //TEXTURE
  291.     //blackout texture
  292.     memset(texture,0,T_WIDTH*T_HEIGHT);
  293.  
  294.     //thrash the dumb MS format...
  295.     thrash=(byte *)malloc(bf->width*bf->height);
  296.     if(thrash==NULL) {
  297.         mode_text();
  298. //        printf("Not enough memory (%lu) for temporary bitmap thrashing area.\n",farcoreleft());
  299.         exit(FAILURE);
  300.     }
  301.     fread(thrash,bf->width*bf->height,1,bmp);
  302.  
  303.     //dword align
  304.     if((bf->width&3)!=0)
  305.         BWIDTH=bf->width+(4-(bf->width&3));
  306.     else
  307.         BWIDTH=bf->width;
  308.  
  309.     //compute picture along x
  310.     w_src=0;
  311.     w_dst=0;
  312.     w=bf->width;
  313.     if(w>T_WIDTH) { w_src=((w-T_WIDTH)>>1); w=T_WIDTH; }
  314.     if(w<T_WIDTH) w_dst=(T_WIDTH-w)>>1;
  315.  
  316.     //compute along y
  317.     h_src=0;
  318.     h_dst=0;
  319.     h=bf->height;
  320.     if(h>T_HEIGHT) { h_src=((h-T_HEIGHT)>>1); h=T_HEIGHT; }
  321.     if(h<T_HEIGHT) h_dst=((T_HEIGHT-h)>>1);
  322.  
  323.     //
  324.     source=thrash+((bf->height-1)*BWIDTH)+w_src-(h_src*BWIDTH);
  325.     destination=texture+w_dst+h_dst*T_WIDTH;
  326.  
  327.     for(y=0;y<h;y++)
  328.     {
  329.         memcpy(destination,source,w);
  330.         source-=BWIDTH;
  331.         destination+=T_WIDTH;
  332.     }
  333.     free(thrash);
  334.  
  335.     free(bf);
  336.  
  337.     fclose(bmp);
  338.     return SUCCESS;
  339. }
  340.  
  341.  
  342. //fps
  343. byte fpsset[8][24]={
  344.     " ###### ######   ####   ",
  345.     " #      #     # #    #  ",
  346.     " #      #     # #       ",
  347.     " #####  ######   ####   ",
  348.     " #      #            #  ",
  349.     " #      #            #  ",
  350.     " #      #       #    #  ",
  351.     " #      #        ####   "
  352. };
  353.  
  354. byte charset[10][8][8]={
  355.   //0
  356.  {"  ##### ",
  357.   " #     #",
  358.   " #     #",
  359.   " #     #",
  360.   " #     #",
  361.   " #     #",
  362.   "  ##### ",
  363.   "        "},
  364.   //1
  365.  {"     ## ",
  366.   "      # ",
  367.   "      # ",
  368.   "      # ",
  369.   "      # ",
  370.   "      # ",
  371.   "     ###",
  372.   "        "},
  373.   //2
  374.  {"   #### ",
  375.   "  #    #",
  376.   "       #",
  377.   "    ### ",
  378.   "   #    ",
  379.   "  #    #",
  380.   "  ##### ",
  381.   "        "},
  382.   // 3
  383.  {"  ##### ",
  384.   " #     #",
  385.   "       #",
  386.   "   #### ",
  387.   "       #",
  388.   " #     #",
  389.   "  ##### ",
  390.   "        "},
  391.   //4
  392.  {"    ##  ",
  393.   "   # #  ",
  394.   "  #  #  ",
  395.   " ###### ",
  396.   "     #  ",
  397.   "     #  ",
  398.   "    ### ",
  399.   "        "},
  400.   //5
  401.  {" #######",
  402.   " #      ",
  403.   " #      ",
  404.   " ###### ",
  405.   "       #",
  406.   " #     #",
  407.   "  ##### ",
  408.   "        "},
  409.   //6
  410.  {"  ##### ",
  411.   " #      ",
  412.   " #      ",
  413.   " ###### ",
  414.   " #     #",
  415.   " #     #",
  416.   "  ##### ",
  417.   "        "},
  418.   //7
  419.  {"  ######",
  420.   " #     #",
  421.   "      # ",
  422.   "     #  ",
  423.   "    #   ",
  424.   "    #   ",
  425.   "    #   ",
  426.   "        "},
  427.   //8
  428.  {"  ##### ",
  429.   " #     #",
  430.   " #     #",
  431.   "  ##### ",
  432.   " #     #",
  433.   " #     #",
  434.   "  ##### ",
  435.   "        "},
  436.   //9
  437.  {"  ##### ",
  438.   " #     #",
  439.   " #     #",
  440.   "  ######",
  441.   "       #",
  442.   "      # ",
  443.   "  ####  ",
  444.   "        "}
  445. };
  446.  
  447.  
  448. //setup the fps counter...
  449. void setup_fps()
  450. {
  451.     int c,x,y;
  452.     byte *vid=(byte *)composite+(8*WIDTH);
  453.  
  454.     //change the 0 to 9 charset from spaces and pound-signs
  455.     //into 0 and 255 (ie, black and white).
  456.     for(c=0;c<=9;c++)
  457.         for(y=0;y<=7;y++)
  458.             for(x=0;x<=7;x++)
  459.                 if(charset[c][y][x]=='#')
  460.                     charset[c][y][x]=255;
  461.                 else
  462.                     charset[c][y][x]=0;
  463.  
  464.     //draw a "FPS" right below where the fps will be.
  465.     //yes, it's slow C code, but here that's ok.
  466.     for(y=0;y<=7;y++)
  467.         for(x=0;x<=23;x++)
  468.             if(fpsset[y][x]=='#')
  469.                 vid[y*WIDTH+x]=255;
  470.             else
  471.                 vid[y*WIDTH+x]=0;
  472. }
  473.  
  474.  
  475. //draw a counter number at the top left of the graphics screen
  476. void print_fps(int fps)
  477. {
  478.     int digits=6;
  479.     char s[16];
  480.     int count=0;
  481.     word x_offset=0;
  482.     int c,x,y;
  483.     byte *src,*dst;
  484.  
  485.     //
  486.     sprintf(s,"%d",fps);
  487.  
  488.     //
  489.     while((s[count]!=NULL)&&(count<digits)) {
  490.         c=(s[count++]-'0');
  491.         src=(byte *)charset+c*8*8;
  492.         dst=(byte *)composite+x_offset;
  493.         for(y=0;y<8;y++) {
  494.             for(x=0;x<8;x++) {
  495.                 *dst=*src;
  496.                 dst++;
  497.                 src++;
  498.             }
  499.             dst+=WIDTH-8;
  500.         }
  501.         x_offset+=8;
  502.     }
  503.  
  504.     //ok. we wrote out the digits. now cleanup anything left over from the
  505.     //last time on the right. we assume no more than 6 digits MAX.
  506.     dst=(char *)composite+x_offset;
  507.     for(y=0;y<8;y++) {
  508.         for(x=x_offset;x<digits*8;x++) {
  509.             *dst++=0;
  510.         }
  511.         dst+=WIDTH-((digits*8)-x_offset);
  512.     }
  513. }
  514.  
  515.  
  516. void show_colors(void)
  517. {
  518.     byte *p;
  519.     int n,w;
  520.     //display the color palette for us under the "fps"
  521.     p=(byte *)composite+WIDTH*16;
  522.     for(n=0;n<64;n++,p+=WIDTH) {
  523.         for(w=0;w<8;w++) {
  524.             *(p+w)=n;
  525.             *(p+w+8)=n+64;
  526.             *(p+w+16)=n+128;
  527.             *(p+w+24)=n+192;
  528.         }
  529.     }
  530.     //show us the bilinear antialiasing matrix column0. It SHOULD be an
  531.     //exact match to the color palette. :)
  532.     p=(byte *)composite+WIDTH*(32+64);
  533.     for(n=0;n<64;n++,p+=WIDTH) {
  534.         for(w=0;w<8;w++) {
  535.             *(p+w)=palette_matrix[n];
  536.             *(p+w+8)=palette_matrix[n+64];
  537.             *(p+w+16)=palette_matrix[n+128];
  538.             *(p+w+24)=palette_matrix[n+192];
  539.         }
  540.     }
  541. }
  542.  
  543.  
  544. //this is the fixed-point version of the scaling/rotation routine.
  545. //since we want maximum speed while still remaining in C parts of this
  546. //may be hard to read compared to the general rotate/scale routine.
  547. //It is similiar to the mathematical version except it uses 16.16
  548. //fixed-point and computes an initial texture vector then does something
  549. //similiar to a two-level line drawing routine, ok?
  550. void FixedRotateScale(float scale, //the scaling factor
  551.                       float angle) //the rotation angle
  552. {
  553.     int sinas=sin(-angle)*65536*scale;
  554.     int cosas=cos(-angle)*65536*scale;
  555.  
  556.     //x' = cos(-angle)+sin(-angle)
  557.     //y' = cos(-angle)-sin(-angle)
  558.     int xc=T_WIDTH_CENTER*65536 - (W_HEIGHT_CENTER*(cosas+sinas));
  559.     int yc=T_HEIGHT_CENTER*65536 - (W_WIDTH_CENTER*(cosas-sinas));
  560.  
  561.     int tx,ty;
  562.     int x,y;
  563.     int tempx,tempy;
  564.     char *screen=composite+WIDTH_OFFSET+HEIGHT_OFFSET*WIDTH;
  565.  
  566.     for (y=0;y<W_HEIGHT;y++)
  567.     {
  568.         tx=xc; ty=yc;
  569.         for(x=0;x<W_WIDTH;x++)
  570.         {
  571.             tempx=(tx>>16); tempy=(ty>>16);
  572.             if( (tempx<T_LEFT) || //clip
  573.                 (tempx>=T_RIGHT) ||
  574.                 (tempy<T_TOP) ||
  575.                 (tempy>=T_BOTTOM) )
  576.                 screen[x]=0; //clip to black
  577.             else
  578.                  screen[x]=texture[tempx+tempy*T_WIDTH]; //draw texel
  579.  
  580.             tx+=cosas; ty-=sinas;
  581.         }
  582.         screen+=WIDTH; xc+=sinas; yc+=cosas;
  583.     }
  584. }
  585.  
  586.  
  587. //this is the revised floating-point version of the scaling/rotation routine.
  588. //now that I finally have a cpu that actually supports FPU op-code
  589. //(from a 486sx25 to a 486dx4-100) thought I'd try them out.
  590. //note that unlike the pure mathematical version, we compute the vector
  591. //of rotation just once at the beginning of the function.
  592. void FloatRotateScale(float scale, //the scaling factor
  593.                       float angle) //the rotation angle
  594. {
  595.     float sinas=sin(-angle)*scale;
  596.     float cosas=cos(-angle)*scale;
  597.  
  598.     //x' = cos(-angle)+sin(-angle)
  599.     //y' = cos(-angle)-sin(-angle)
  600.     float xc=T_WIDTH_CENTER - (W_HEIGHT_CENTER*(cosas+sinas));
  601.     float yc=T_HEIGHT_CENTER - (W_WIDTH_CENTER*(cosas-sinas));
  602.  
  603.     float tx, ty;
  604.     int x,y;
  605.     //actually to composite buffer and not to screen...
  606.     //but it can be changed easily.
  607.     char *screen=composite+WIDTH_OFFSET+HEIGHT_OFFSET*WIDTH;
  608.  
  609.     for (y=0;y<W_HEIGHT;y++)
  610.     {
  611.         tx=xc; ty=yc;
  612.         for (x=0;x<W_WIDTH;x++)
  613.         {
  614.             if( (tx<(float)T_LEFT) ||
  615.                 (tx>=(float)T_RIGHT) ||
  616.                 (ty<(float)T_TOP) ||
  617.                 (ty>=(float)T_BOTTOM) )
  618.                 screen[x]=0;
  619.             else
  620.                 screen[x]=texture[(int)(tx)+(((int)ty)*T_WIDTH)];
  621.  
  622.             tx+=cosas; ty-=sinas;
  623.         }
  624.         screen+=WIDTH; xc+=sinas; yc+=cosas;
  625.     }
  626. }
  627.  
  628.  
  629. //This is the pure mathematical version of rotation and scaling.
  630. //It is naturally slow since it has not be optimized to take advantage
  631. //of the way computers currently operate. Nevertheless it can help
  632. //some of you understand what is going on in the other routines.
  633. void MathematicalRotateScale(float scale,
  634.                              float angle)
  635. {
  636.     //precompute the cosine and sine values used to speed things up
  637.     float cosas=cos(angle)*scale;
  638.     float sinas=sin(angle)*scale;
  639.     float xc, yc;
  640.     float tx, ty;
  641.     int x,y;
  642.     char *screen;
  643.  
  644.     for (y=0;y<W_HEIGHT;y++)
  645.     {
  646.         for (x=0;x<W_WIDTH;x++)
  647.         {
  648.             //compute the center of the texture bitmap
  649.             xc=(float)(x-W_WIDTH_CENTER);
  650.             yc=(float)(y-W_HEIGHT_CENTER);
  651.  
  652.             //compute the translation of x and y into texture map
  653.             //x' = x*cos(angle) - y*sin(angle) +160
  654.             //y' = x*sin(angle) + y*cos(angle) +100
  655.             tx=( (xc * cosas) - (yc * sinas) ) + (float)T_WIDTH_CENTER;
  656.             ty=( (xc * sinas) + (yc * cosas) ) + (float)T_HEIGHT_CENTER;
  657.  
  658.             //compute the pixel on the composite screen buffer to draw to
  659.             screen=composite+(x+W_LEFT)+((y+W_TOP)*WIDTH);
  660.  
  661.             //clip to black any texels that fall off of our 320x200 map
  662.             if( (tx<(float)T_LEFT) ||
  663.                 (tx>=(float)T_RIGHT) ||
  664.                 (ty<(float)T_TOP) ||
  665.                 (ty>=(float)T_BOTTOM) )
  666.                 *screen=0; //clipped to black
  667.             else
  668.                 *screen=texture[ (int)(tx) + ( (int)(ty)*T_WIDTH) ]; //texel
  669.         }
  670.     }
  671. }
  672.  
  673.  
  674. //post bilinear antialiasing
  675. void bilinear()
  676. {
  677.     int line, x;
  678.     byte *p=(byte *)composite+WIDTH_OFFSET+WIDTH+1; //x=61 y=1
  679.     for(line=HEIGHT-2;line>0;line--) {
  680.         for(x=W_WIDTH-2;x>0;x--) {
  681.             *p=(( (*p) + ( ( *(p+1)+*(p-1)+*(p-WIDTH)+*(p+WIDTH) ) >>2 ) )>>1);
  682.             p++;
  683.         }
  684.         p+=2*WIDTH_OFFSET+2;
  685.     }
  686. }
  687.  
  688.  
  689. //post trilinear antialiasing
  690. void trilinear()
  691. {
  692.     int line, x;
  693.     byte *p=(byte *)composite+WIDTH_OFFSET+WIDTH+1;
  694.     for(line=HEIGHT-2;line>0;line--) {
  695.         for(x=W_WIDTH-2;x>0;x--) {
  696.             *p=(( (*p) + ( (*(p+1)+*(p-1)+*(p-WIDTH)+*(p+WIDTH)+*(p-WIDTH-1)+*(p-WIDTH+1)+*(p+WIDTH-1)+*(p+WIDTH+1)) >>3 ) )>>1);
  697.             p++;
  698.         }
  699.         p+=2*WIDTH_OFFSET+2;
  700.     }
  701. }
  702.  
  703.  
  704. //post hyperlinear? antialiasing. This is just an experiment.
  705. void hyperlinear()
  706. {
  707.     int line, x;
  708.     byte c;
  709.     byte *p=(byte *)composite+WIDTH_OFFSET+WIDTH+1;
  710.     for(line=HEIGHT-2;line>0;line--) {
  711.         for(x=W_WIDTH-2;x>0;x--) {
  712.             c=(( (*p) + ( (*(p+1)+*(p-1)+*(p-WIDTH)+*(p+WIDTH)+*(p-WIDTH-1)+*(p-WIDTH+1)+*(p+WIDTH-1)+*(p+WIDTH+1)) >>3 ) )>>1);
  713.             *(p-WIDTH-1)=c;
  714.             *(p-WIDTH+1)=c;
  715.             *(p+WIDTH-1)=c;
  716.             *(p+WIDTH+1)=c;
  717.             p++;
  718.         }
  719.         p+=2*WIDTH_OFFSET+2;
  720.     }
  721. }
  722.  
  723.  
  724. //prime is the pixel in the center. fourth is one of the four sourrounding
  725. //pixels in bilinear antialiasing.
  726. void setup_matrix()
  727. {
  728.     int match,diff;
  729.     int d;
  730.     int n;
  731.     int prime,derv;
  732.     int red,green,blue;
  733.  
  734.     for(derv=0;derv<256;derv++) {
  735.         for(prime=0;prime<256;prime++) {
  736.             //compute the color component differences for red,
  737.             //green, and blue of the prime and the fourth.
  738.             //this rgb is the weighted average of the prime and the fourth.
  739.             red=(int)(palette[derv].red*.25+palette[prime].red*.75);
  740.             green=(int)(palette[derv].green*.25+palette[prime].green*.75);
  741.             blue=(int)(palette[derv].blue*.25+palette[prime].blue*.75);
  742.  
  743.             //find the closet color in the 256 color palette
  744.             for(match=0,diff=3*256,n=0;n<256;n++) {
  745.                 d=abs(palette[n].red-red)+abs(palette[n].green-green)+abs(palette[n].blue-blue);
  746.                 if(d<diff) { match=n; diff=d; }
  747.             }
  748.  
  749.             //add new entry to palette matrix
  750.             palette_matrix[derv*256+prime]=match;
  751.         }
  752.         printf(".");
  753.     }
  754.     printf("\n");
  755. }
  756.  
  757.  
  758. //post bilinear antialiasing
  759. void color_bilinear()
  760. {
  761.     int line, x;
  762.     byte c,cc;
  763.     byte *p=(byte *)composite+WIDTH_OFFSET+WIDTH+1; //x=61 y=1
  764.     for(line=HEIGHT-2;line>0;line--) {
  765.         for(x=W_WIDTH-2;x>0;x--) {
  766.             c=*p;
  767.             c=palette_matrix[ c + ((*(p-1))<<8)     ];
  768.             c=palette_matrix[ c + ((*(p+1))<<8)     ];
  769.             c=palette_matrix[ c + ((*(p-WIDTH))<<8) ];
  770.             c=palette_matrix[ c + ((*(p+WIDTH))<<8) ];
  771.             *(p++)=c;
  772.         }
  773.         p+=2*WIDTH_OFFSET+2;
  774.     }
  775. }
  776.  
  777.  
  778. //this is the original color bilinear antialiasing routine.
  779. //it works but is very slow.
  780. void accurate_color_bilinear()
  781. {
  782.     int n,match,diff;
  783.     int line,x;
  784.     int red,green,blue;
  785.     int d;
  786.     byte c;
  787.     byte *p=(byte *)composite+WIDTH_OFFSET+WIDTH+1; //x=61 y=1
  788.     for(line=HEIGHT-2;line>0;line--) {
  789.         for(x=W_WIDTH-2;x>0;x--) {
  790.             //
  791.             c=*(p-1);
  792.             red=palette[c].red;
  793.             green=palette[c].green;
  794.             blue=palette[c].blue;
  795.  
  796.             c=*(p+1);
  797.             red+=palette[c].red;
  798.             green+=palette[c].green;
  799.             blue+=palette[c].blue;
  800.  
  801.             c=*(p-WIDTH);
  802.             red+=palette[c].red;
  803.             green+=palette[c].green;
  804.             blue+=palette[c].blue;
  805.  
  806.             c=*(p+WIDTH);
  807.             red+=palette[c].red;
  808.             green+=palette[c].green;
  809.             blue+=palette[c].blue;
  810.  
  811.             red=red>>2;
  812.             green=green>>2;
  813.             blue=blue>>2;
  814.  
  815.             c=*p;
  816.             red+=palette[c].red;
  817.             green+=palette[c].green;
  818.             blue+=palette[c].blue;
  819.  
  820.             red=red>>1;
  821.             green=green>>1;
  822.             blue=blue>>1;
  823.  
  824.             //
  825.             for(match=0,diff=1000,n=0;n<256;n++) {
  826.                 d=abs(palette[n].red-red)+abs(palette[n].green-green)+abs(palette[n].blue-blue);
  827.                 if(d<diff) { match=n; diff=d; }
  828.             }
  829.  
  830.             //
  831.             *p=match;
  832.             p++;
  833.         }
  834.         p+=2*WIDTH_OFFSET+2;
  835.     }
  836. }
  837.  
  838.  
  839. //copy the composite buffer to the VGA screen
  840. void copycomposite()
  841. {
  842.     memcpy(G_BASE,composite,WIDTH*HEIGHT);
  843. }
  844.  
  845.  
  846. //clear the composite buffer
  847. void clearcomposite()
  848. {
  849.     memset(composite,0,WIDTH*HEIGHT);
  850. }
  851.  
  852.  
  853. // "You had all of them on your side? didn't you?" --NIN
  854. int main(int argc,char *argv[])
  855. {
  856.     float angle=PI/256.0;
  857.     float angle_v=-PI/128.0;
  858.     float scale=1.05;
  859.     int n;
  860.     int alias=0, render=0, grayscale=TRUE;
  861.     int key='~',key2=0; //so as not to trip up the arrow keys below
  862.     int frames=0;
  863.  
  864.     mode_text();
  865.     printf("Scaling/Rotation/Antialiasing Prototyper by Minimalist 1995-1996.\n");
  866. //         printf("Last compiled %s %s. %d lines of C code.\n",__DATE__,__TIME__,lines());
  867.     #ifdef __WATCOMC__
  868.          printf("Using 32-bit compiler Watcom C version %d.%d.\n\n",
  869.          (__WATCOMC__)/100,(__WATCOMC__%100));
  870.     #endif
  871.  
  872.     //you did specify a filename didn't you?
  873.     if(argc!=2)
  874.     {
  875.         printf("Use: ALIASWC 'filename.bmp'\n");
  876.         return(FAILURE);
  877.     }
  878.  
  879.     printf("Allocating palette.\n");
  880.     palette=(void *)malloc(3*256);
  881.     if(palette==NULL) {
  882.         mode_text();
  883. //      printf("Not enough memory (%lu) for palette.\n",farcoreleft());
  884.         exit(FAILURE);
  885.     }
  886.  
  887.     printf("Allocating texture.\n");
  888.     texture=(char *)malloc(T_WIDTH*T_WIDTH);
  889.     if(texture==NULL) {
  890.         mode_text();
  891. //        printf("Not enough memory (%lu) for texture map.\n",farcoreleft());
  892.         exit(FAILURE);
  893.     }
  894.  
  895.     //create a composite buffer (off-screen double buffer)
  896.     printf("Allocating composite buffer.\n");
  897.     composite=(char *)malloc(WIDTH*HEIGHT);
  898.     if(composite==NULL) {
  899.         mode_text();
  900. //        printf("Not enough memory (%lu) for composite buffer.\n",farcoreleft());
  901.         exit(FAILURE);
  902.     }
  903.  
  904.     //initialize our table of n*320
  905.     printf("Allocating y320.\n Computing y[0,%d).\n",HEIGHT);
  906.     y320=(int *)malloc(sizeof(int)*HEIGHT);
  907.     if(y320==NULL) {
  908.         mode_text();
  909. //        printf("Not enough memory (%lu) for y320 table.\n",farcoreleft());
  910.         exit(FAILURE);
  911.     }
  912.     for(n=0;n<HEIGHT;n++) y320[n]=n*WIDTH;
  913.  
  914.     printf("Load image [%s].\n",argv[1]);
  915.     if(LoadTestImage(argv[1])==FAILURE)
  916.     {
  917.         mode_text();
  918.         printf("The file %s does not exist.\n",argv[1]);
  919.         return(FAILURE);
  920.     }
  921.  
  922.     printf("Allocating palette_matrix.\n Computing Color Bilinear Antialiasing matrix");
  923.     palette_matrix=(byte *)malloc(256*256);
  924.     if(palette_matrix==NULL) {
  925.         mode_text();
  926. //        printf("Not enough memory (%lu) for y320 table.\n",farcoreleft());
  927.         exit(FAILURE);
  928.     }
  929.     setup_matrix();
  930.  
  931.  
  932.     //inpho
  933.     mode_text();
  934.     printf("Scaling/Rotation/Antialiasing Prototyper 3 by Minimalist 1995-1996.\n");
  935. //         printf("Last compiled %s %s. %d lines of C code.\n",__DATE__,__TIME__,lines());
  936.     #ifdef __WATCOMC__
  937.         printf("Using 32-bit compiler Watcom C version %d.%d.\n\n",
  938.         (__WATCOMC__)/100,(__WATCOMC__%100));
  939.     #endif
  940. //    printf("Memory %u. Stack %u.\n",_memavl(),stackavail());
  941. /*
  942.     if(_control87)
  943.         printf("FPU:%d87.",_8087);
  944.     else
  945.         printf("No FPU.");
  946. */
  947.     //the propaganda
  948.     printf("This program requires at least a 486 with an integrated 387 grade FPU\n");
  949.     printf("and the DOS Extender DOS4GW.EXE or a compatible.\n");
  950.  
  951.     printf("You may use any of the following keys:\n");
  952.     printf(" ESC will exit the program\n");
  953.     printf(" C   Color antialiasing\n");
  954.     printf(" G   Fast grayscale antialiasing\n");
  955.  
  956.     printf("Scaling and Rotation:\n");
  957.     printf(" I   Integer fixed-point Optimized\n");
  958.     printf(" F   Floating-point Optimized\n");
  959.     printf(" M   Mathematical floating-point\n");
  960.  
  961.     printf("Antialiasing Filters:\n");
  962.     printf(" N   No Antialiasing\n");
  963.     printf(" B   Post Bilinear Antialiasing\n");
  964.     printf(" T   Post Trilinear Antialiasing (GRAYSCALE ONLY)\n");
  965.     printf(" H   Post um... ghosting/Antialiasing? (GRAYSCALE ONLY)\n");
  966.     printf(" A   Accurate Bilinear Color Antialiasing (COLOR ONLY) (SLOW!)\n");
  967.  
  968.     printf("To rotate use left/right arrows. To scale use up/down arrows.\n");
  969.     printf("Pressing Ctrl w/ arrows will increase speed. Use BACKSPACE to stop.\n\n");
  970.  
  971.     //wait for windows to quit thrashing the hard drive...
  972.     printf("Press any key (except ESC) to start...\n");
  973.     while (!kbhit()); getch();
  974.  
  975.     //set things up
  976.     mode_graphic();
  977.  
  978.     clearcomposite();
  979.     setup_fps();
  980.     show_colors();
  981.     change_timer();
  982.  
  983.     //the main loop
  984.     while (key!=27) {
  985.         if(kbhit()) {
  986.             key=toupper(getch());
  987.             switch (key) {
  988.                 //internal yazzie testing frame for...
  989.                 //and sissy
  990.                 case 'S':
  991.                     angle-=PI/4.0;
  992.                     angle_v=0.0;
  993.                     break;
  994.                 //and susy honey
  995.                 case 'U':
  996.                     angle+=PI/4.0;
  997.                     angle_v=0.0;
  998.                     break;
  999.                 //and prissy
  1000.                 case 'Z':
  1001.                     scale=0.5;
  1002.                     angle=PI/2.0;
  1003.                     angle_v=-0.1;
  1004.                     break;
  1005.                 //and yazzie :)
  1006.                 case 'Y':
  1007.                     angle=0.0;
  1008.                     angle_v=0.0;
  1009.                     scale=1.0;
  1010.                     break;
  1011.  
  1012.                 case 'I': render=0; break;
  1013.                 case 'F': render=1; break;
  1014.                 case 'M': render=2; break;
  1015.                 case 'W': render=3; break;
  1016.  
  1017.                 case 'N': alias=1; break;
  1018.                 case 'B': alias=2; break;
  1019.                 case 'T':
  1020.                 case 'A': alias=3; break;
  1021.                 case 'H': alias=4; break;
  1022.  
  1023.                 case 'C': grayscale=FALSE; break;
  1024.                 case 'G': grayscale=TRUE; break;
  1025.  
  1026.                 case 0:
  1027.                     key2=getch();
  1028.                     switch (key2) {
  1029.                         //rotation
  1030.                         case 75: angle_v+=PI/256.0; break; //left arrow
  1031.                         case 77: angle_v-=PI/256.0; break; //right arrow
  1032.                         case 115: angle_v+=PI/32.0; break; //left arrow
  1033.                         case 116: angle_v-=PI/32.0; break; //right arrow
  1034.                         //scale
  1035.                         case 72: scale-=0.05; break;
  1036.                         case 80: scale+=0.05; break;
  1037.                         case 141: scale-=0.5; break;
  1038.                         case 145: scale+=0.5; break;
  1039.                     }
  1040.                     break;
  1041.                 }
  1042.             }
  1043.  
  1044.             switch (render) {
  1045.                 case 0: FixedRotateScale(scale,angle); break;
  1046.                 case 1: FloatRotateScale(scale,angle); break;
  1047.                 case 2: MathematicalRotateScale(scale,angle); break;
  1048.             }
  1049.  
  1050.             switch (grayscale) {
  1051.                 case FALSE: {
  1052.                     switch (alias) {
  1053.                       //case 1: do nothing....
  1054.                         case 2: color_bilinear(); break;
  1055.                         case 3: accurate_color_bilinear(); break;
  1056.                     }
  1057.                     break;
  1058.                 case TRUE: {
  1059.                     switch (alias) {
  1060.                       //case 1: do nothing....
  1061.                         case 2: bilinear(); break;
  1062.                         case 3: trilinear(); break;
  1063.                         case 4: hyperlinear(); break;
  1064.                     }
  1065.                     break;
  1066.                 }
  1067.             }
  1068.         }
  1069.  
  1070.         copycomposite(); //show us the composite buffer!
  1071.  
  1072.         angle+=angle_v;
  1073.         if(angle>2*PI) angle-=2*PI; //bound our angle...
  1074.         if(angle<-2*PI) angle+=2*PI;
  1075.  
  1076.         //do the FPS calcing
  1077.         frames++;
  1078.         if(second_flag) { //been a second yet?
  1079.             print_fps(frames); //yes, so see how many frames we've done in that time.
  1080.             second_flag=FALSE;
  1081.             frames=0; //and the frames
  1082.         }
  1083.     }
  1084.  
  1085.     //restore things to normal
  1086.     restore_timer();
  1087.     free(composite);
  1088.     free(palette);
  1089.     free(texture);
  1090.     free(y320);
  1091.     free(palette_matrix);
  1092.  
  1093.     //parting words....
  1094.     mode_text();
  1095.     printf("By Minimalist (Lewis A. Sellers) 1995-96. Part of the C/Pascal/Asm package.\n");
  1096.     printf("To contact, email: lsellers@1stresource.com (shortly to be lsellers@usit.net).\n");
  1097.     printf("or drop by http://www.dwc.edu/grail, site of Grail Operating System Project.\n\n");
  1098.  
  1099.     printf("#coders home page: http://www.realtime.net/~dlinvill/coders/index.html\n\n");
  1100.  
  1101.     printf("Psst. Testing out the original code or modification you did to it? Then press\n");
  1102.     printf("Z to set a standard scale and rotation factor. On a 486dx4 100mhz 256kb cache\n");
  1103.     printf("60ns DRAM, and an awful PCI Trio32 S3 graphics card:\n");
  1104.     printf("                       I=~43fps  F=~7fps  M=~5fps\n");
  1105.     printf("      I/Grayscale Bilinear=~27fps  Trilinear=~23fps  Hyperlinear=~21.5fps\n");
  1106.     printf("                        I/Color Bilinear=~19fps\n\n");
  1107.  
  1108.     printf("         'It was men like me that built the bomb.' --paraphrased, T2\n\n");
  1109.  
  1110.     return(SUCCESS);
  1111. }
  1112.  
  1113.  
  1114. //cute trick of mine for single file programs
  1115. //int lines() { return __LINE__+1; }
  1116.